/**
* AutoSWF - Cody Cushing. March 26, 2009
* Copyright (c) 2009 Cody Cushing
* No use restrictions. Maintain this notice in all versions. 
**/

package com.autoswf.core
{
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.utils.Dictionary;

	/**
	 * Class for automating an InteractiveObject. Not required, just convenient.
	 */
	public class SpriteChainLink extends Sprite implements IChainLink
	{
		public static const DELIMITER:String = Delimiters.PATH_DELIMITER;
		
		protected var chainLink:ChainLink;
		protected var events:Dictionary;
		
		
		/**
		 * Constructor.
		 */
		public function SpriteChainLink(id:String)
		{
			super();
			
			chainLink = new ChainLink(id);
			chainLink.client = this;
			
			events = new Dictionary(true);
		}
		
		public function get id():String
		{
			return chainLink.id;
		}
		
		public function addChildLink(childChainLink:IChainLink):void
		{
			chainLink.addChildLink(childChainLink);
		}
		
		public function removeChildLink(childChainLink:IChainLink):void
		{
			chainLink.removeChildLink(childChainLink);
		}
		
		public function addParentLink(parentChainLink:IChainLink):void
		{
			chainLink.addParentLink(parentChainLink);
		}
		
		public function removeParentLink(parentChainLink:IChainLink):void
		{
			chainLink.removeParentLink(parentChainLink);
		}
		
		public function sendUpChain(param:*):void
		{
			chainLink.sendUpChain(param);
		}
		
		
		/**
		 * Checks if transport object is an event and if this class has that event listener,  
		 * invokes the handler, passing the event. Otherwise, the object is passed down the chain.
		 */
		public function sendDownChain(path:*):String
		{
			var transport:Transport = Transport(path);
			if(transport.proposition is Event)
			{
				var event:Event = transport.proposition;
				if(events.hasOwnProperty(event.type))
				{
					for each(var listener:Function in events[event.type])
					{
						listener(event);
					}
				}
				return null
			}
			return chainLink.sendDownChain(path);
		}
		
		
		/**
		 * Generates a function to proxy event handling for tracking/automation before 
		 * forwarding the event to handler function.
		 */
		public function addTrackingEventListener(type:String, listener:Function, useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false):void
		{
			if(!events.hasOwnProperty(type))
			{
				events[type] = new Dictionary(false);
			}
			
 			events[type][listener] = function(event:Event):void
			{
				chainLink.sendUpChain(event);   /* Bubble events up */
				listener(event);                /* Invoke handler */
			}
			
			this.addEventListener(type, events[type][listener], useCapture, priority, useWeakReference);
		}
		
		
		public function hasTrackingEventListener(type:String, listener:Function = null):Boolean
		{
			return (listener != null && events[type] != null) ? events[type].hasOwnProperty(listener) : events.hasOwnProperty(type);
		}
		
		
		/**
		 * Removes proxy function as handler for event type, deletes proxy function.
		 */
		public function removeTrackingEventListener(type:String, listener:Function, useCapture:Boolean = false):void
		{
			if(events[type] && events[type][listener])
			{
				this.removeEventListener(type, events[type][listener], useCapture);
				delete events[type][listener];
				
				/* short cut to remove valueless key from dictionary */
				for each(var func:Function in events[type]){ }
				
				if(func == null)
				{
					delete events[type];
				}
			}
		}
		
	}
}